package com.lanou3g.ptp.task.service.impl;

import com.alibaba.dubbo.config.annotation.Reference;
import com.alibaba.dubbo.config.annotation.Service;
import com.alibaba.fastjson.JSON;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.lanou3g.ptp.achievement.service.DiaryService;
import com.lanou3g.ptp.entity.Task;
import com.lanou3g.ptp.sso.service.SsoService;
import com.lanou3g.ptp.vo.TaskVO;
import com.lanou3g.ptp.entity.*;
import com.lanou3g.ptp.signInDate.service.SignInDateService;
import com.lanou3g.ptp.task.mapper.TaskMapper;
import com.lanou3g.ptp.task.service.TaskService;
import com.lanou3g.ptp.taskrole.service.TaskRoleService;
import com.lanou3g.ptp.taskstudent.service.TaskStudentService;
import org.apache.activemq.command.ActiveMQTopic;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.jms.core.JmsTemplate;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.concurrent.TimeUnit;

@Service(interfaceClass = TaskService.class)
public class TaskServiceImpl implements TaskService {

    @Autowired
    private StringRedisTemplate redisTemplate;

    @Value("${REDIS_TASK_KEY_PREFIX}")
    private String REDIS_TASK_KEY_PREFIX;

    @Value("${REDIS_TASK_KEY_EXPIRE}")
    private Long REDIS_TASK_KEY_EXPIRE;
    @Value("TASK-INSERT")
    private String ACTIVEMQ_TOPIC_TASK_KEY;
    @Autowired
    private TaskRoleService taskRoleService;
    @Autowired
    private TaskStudentService taskStudentService;
    @Autowired
    private SignInDateService signInDateService;
    @Autowired
    private TaskMapper taskMapper;
    @Reference
    private DiaryService diaryService;
    @Reference
    private SsoService ssoService;
    @Autowired
    private JmsTemplate template;

    private ArrayList<Date> days(TaskVO taskVO, Calendar cal, Calendar cal2){
        //起始时间和结束时间间隔多少天
//            int a = (int) ((taskEndTime.getTime() - taskStartTime.getTime()) / (1000 * 60 * 60 * 24));
        int day1 = cal.get(Calendar.DAY_OF_YEAR);
        int day2 = cal2.get(Calendar.DAY_OF_YEAR);
        int a ;
        int year1 = cal.get(Calendar.YEAR);
        int year2 = cal2.get(Calendar.YEAR);
        if (year1 != year2){
            int timeDistance = 0;
            for (int i = year1; i < year2; i++) {
                if (i % 4 == 0 && i % 100 != 0 || i % 400 == 0) {//闰年,几乎用不到
                    timeDistance += 366;
                }else{
                    timeDistance +=365;
                }
            }
             a = timeDistance + (day2 - day1);
        }else {
             a = day2-day1;
        }
        ArrayList<Date> dateList = new ArrayList<>();//
        //此时要处理时间(周一周二等),首先获取星期集合
        ArrayList<Integer> weeks = taskVO.getWeeks();
        //如果集合存在1,代表有星期日,7代表周六
        for (int j =1;j<8;j++){
            if (weeks.contains(j)) {
                for (int i = 0; i < a + 1; i++) {
                    cal.add(Calendar.DATE, i);//i天后的日期
                    if ((cal.get(Calendar.DAY_OF_WEEK)) == j) {//
                        dateList.add(cal.getTime());
                    }
                    cal.setTime(taskVO.getTask().getTaskStartTime());
                }

            }
        }
        return dateList;
    }
    @Override
    public void insert1(TaskVO taskVO,String token){
        ActiveMQTopic taskInsert = new ActiveMQTopic(ACTIVEMQ_TOPIC_TASK_KEY);
        Long id = taskVO.getTask().getId();
        template.convertAndSend(taskInsert,id);
        Object user = ssoService.tokenUser(token);
        if (user instanceof Student){
            taskVO.getTask().setStatus(3);
        }
        insert(taskVO);
    }

    @Transactional
    @Override
    public void insert(TaskVO taskVO) {
        //判断登录用户是不是学生
        //接收TaskVo的json对象进行拆分,首先拆出task对象
        Date date = new Date();
        Task task = taskVO.getTask();
        task.setCreateTime(date);
        task.setUpdateTime(date);
        //执行插入方法插入task对象到表中
        taskMapper.insert(task);
        //拆分出签到时间规则属性
        Integer dateType = taskVO.getDateType();
        //判断时间类型,执行不同的签到规则,处理时间
        //如果签到时间类型为1,不需处理
        ArrayList<SignInDate> signInDateList = new ArrayList<>();//
        if (dateType == 1) {//
            //把每个时间遍历到signInDateList
            ArrayList<Date> signInDates = taskVO.getSignInDates();
            for (Date sDate : signInDates) {
                SignInDate signInDate = new SignInDate();
                signInDate.setCreateTime(date);
                signInDate.setUpdateTime(date);
                signInDate.setStatus(task.getStatus());
                signInDate.setTaskId(task.getId());
                signInDate.setDate(sDate);
                signInDateList.add(signInDate);
            }
            signInDateService.insert(signInDateList);
        } else {
            Date taskStartTime = task.getTaskStartTime();
            Calendar cal = Calendar.getInstance();
            //date转calendar
            cal.setTime(taskStartTime);
            Date taskEndTime = task.getTaskEndTime();
            Calendar cal2 = Calendar.getInstance();
            cal2.setTime(taskEndTime);
            //调用时间分割方法days
            ArrayList<Date> dateList = days(taskVO,cal,cal2);
            //遍历放入数据
            for (Date date1 : dateList) {
                SignInDate signInDate = new SignInDate();
                signInDate.setCreateTime(date);
                signInDate.setUpdateTime(date);
                signInDate.setStatus(task.getStatus());
                signInDate.setTaskId(task.getId());
                signInDate.setDate(date1);
                signInDateList.add(signInDate);
            }
        }
        signInDateService.insert(signInDateList);
        //拆分出taskRoles
        ArrayList<TaskRole> taskRoles = taskVO.getTaskRoles();//
        for (TaskRole taskRole : taskRoles) {
            taskRole.setCreateTime(date);
            taskRole.setUpdateTime(date);
            taskRole.setStatus(task.getStatus());
            taskRole.setGradingType(task.getGradingType());
            taskRole.setTaskId(task.getId());
        }
        taskRoleService.insert(taskRoles);
        //拆分出taskStudentId集合
        ArrayList<Long> taskStudents1 = taskVO.getTaskStudents();//
        ArrayList<TaskStudent> taskStudents = new ArrayList<>();
        for (Long studentId : taskStudents1) {
            TaskStudent taskStudent = new TaskStudent();
            taskStudent.setUpdateTime(date);
            taskStudent.setCreateTime(date);
            taskStudent.setStatus(task.getStatus());
            taskStudent.setTaskId(task.getId());
            taskStudent.setStudentId(studentId);
            taskStudents.add(taskStudent);
        }
        taskStudentService.insert(taskStudents);
    }
    @Transactional
    @Override
    public void delete(Long id) {
        taskMapper.delete(id);
        taskRoleService.deleteByTaskId(id);
        taskStudentService.deleteByTaskId(id);
        signInDateService.deleteByTaskId(id);

    }
    @Transactional
    @Override
    public void deletes(Long[] ids) {
        taskMapper.deletes(ids);
        taskRoleService.deletesByTaskIds(ids);
        taskStudentService.deletesByTaskIds(ids);
        signInDateService.deletesByTaskIds(ids);
    }
    @Transactional
    @Override
    public void update(Long id, TaskVO taskVO,String token) {
        Date date = new Date();
        Task task = taskVO.getTask();
        task.setUpdateTime(date);
        //先删除,再添加
        delete(id);
        insert(taskVO);
    }

    @Override
    public PageInfo<Task> findAll(Integer page,Integer size) {
        PageHelper.startPage(page,size);
        List<Task> all = taskMapper.findAll();
        return new PageInfo<>(all);
    }

    @Override
    public PageInfo<Task> findByKeyword(Integer page, Integer size, String keyword) {
        PageHelper.startPage(page,size);
        List<Task> all = taskMapper.findByKeyword(keyword);
        return new PageInfo<>(all);

    }

    @Override
    public TaskVO findTaskVOById(Long id) {
        String s = REDIS_TASK_KEY_PREFIX + id;
        //通过key去redis里查
        String s1 = redisTemplate.opsForValue().get(s);
        //判断，如果空，先把数据从mybatis里查出来，然后存进redis里
        TaskVO taskVO = new TaskVO();
        if (s1==null){
            Task task = taskMapper.findById(id);
            taskVO.setTask(task);
            ArrayList<TaskRole> taskRoles = taskRoleService.findByTaskId(id);
            taskVO.setTaskRoles(taskRoles);
            ArrayList<Long> taskStudents = taskStudentService.findByTaskId(id);
            taskVO.setTaskStudents(taskStudents);
            String s2 = JSON.toJSONString(taskVO);
            redisTemplate.opsForValue().set(s, s2, REDIS_TASK_KEY_EXPIRE, TimeUnit.SECONDS);
            return taskVO;
        }else {
            redisTemplate.expire(s, REDIS_TASK_KEY_EXPIRE, TimeUnit.SECONDS);
            return JSON.parseObject(s1,TaskVO.class);

        }


    }

    @Override
    public Task findById(Long id) {
        return taskMapper.findById(id);
    }

    @Override
    public Map<String, List<Diary>> diarySituation(Long taskId) {
        HashMap<String, List<Diary>> result = new LinkedHashMap<>();
        List<SignInDate> signTime = signInDateService.findSignTime(taskId);
        for (SignInDate signInDate : signTime) {
            List<Diary> diarySituation = diaryService.findDiarySituation(signInDate.getDate(), taskId);
            result.put(signInDate.getDate().toString(),diarySituation);
        }
        return result;
    }

    @Override
    public List<Task> findAll1(Long teaachlinkId) {
        return taskMapper.findAll1(teaachlinkId);
    }

    @Override
    public void updates(Long[] taskIds, Task task) {
        taskMapper.updates(taskIds,task);
    }
}
